import java.net.*;
import java.io.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.Arrays;

public class CardClient extends JFrame implements Runnable{

	private int port=5656;
	private String host="localhost";
	private String name;
	private Socket socket;
	private Connection conn;
	Player player;
	Table table;
	
	JPanel contentPane;
	public Color backgroundColor = new Color(0,112,26);
	JButton btnStart;
	CardPanel cardPanel;
	CardPanel topPanel;
	CardPanel rightPanel;
	CardPanel leftPanel;
	CardPanel bottomPlayPane;
	CardPanel rightPlayPane;
	CardPanel leftPlayPane;
	ButtonPanel buttonPanel;
	PlayerPanel playerPanel;
	PlayerPanel rightPlayerPanel;
	PlayerPanel leftPlayerPanel;
	ScorePanel  scorePanel;

	
	public CardClient(){
		super("斗地主");
		setSize(800,600);
		setResizable(false);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		this.contentPane=(JPanel)this.getContentPane();
		contentPane.setBackground(new Color(0,112,26));
		init();
		this.setVisible(true);
	}
		
	private void joinGameAction(){
		JoinDialog jf=new JoinDialog(this);
		jf.setLocationRelativeTo(this);
		jf.setVisible(true);
		joinGame(host,port);
	}
	
	public void init(){
		JMenuBar mb = new JMenuBar();
		JMenu mnuGame = new JMenu("游戏");
		mb.add(mnuGame);
		JMenuItem mnuCreatGame = new JMenuItem(new AbstractAction("创建游戏(C)") {
			public void actionPerformed(ActionEvent evt) {
				startServer(port);
			}
		});
		mnuGame.add(mnuCreatGame);

		JMenuItem mnuJoinGame=new JMenuItem(new AbstractAction("加入游戏(J)") {
			public void actionPerformed(ActionEvent evt) {
				joinGameAction();
			}}
		);
		mnuGame.add(mnuJoinGame);
		JMenuItem mnuAddRobot=new JMenuItem(new AbstractAction("添加机器人(A)") {
			public void actionPerformed(ActionEvent evt) {
				addRobot();
			}}
		);
		mnuGame.add(mnuAddRobot);
		this.setJMenuBar(mb);
		contentPane.setLayout(null);

		btnStart = new JButton("开始");
		btnStart.setBounds(new Rectangle(368, 280, 98, 35));
		btnStart.addActionListener(new java.awt.event.ActionListener(){
			public void actionPerformed(ActionEvent e){
				btnStart_actionPerformed(e);
			}
		});
		btnStart.setVisible(false);
		contentPane.add(btnStart);      	
    	
    	cardPanel=new CardPanel(this,CardPanel.BOTTOM);
    	cardPanel.addMouseListener(new CardMouseListener(this));
    	contentPane.add(cardPanel);
    	cardPanel.setBounds(160,400,460,130);
    	cardPanel.setType(0);
    	cardPanel.setVisible(true);
    	
    	bottomPlayPane=new CardPanel(this,CardPanel.BOTTOM_PLAY);
    	contentPane.add(bottomPlayPane);
    	bottomPlayPane.setBounds(250,270,300,100);
    	bottomPlayPane.setType(1);
    	bottomPlayPane.setVisible(true);
    	
    	topPanel=new CardPanel(this,CardPanel.TOP);
    	contentPane.add(topPanel);
    	topPanel.setBounds(275,25,280,100);
    	topPanel.setType(1);
    	topPanel.setCardSpaceX(90);
    	topPanel.setVisible(true);
    	
    	rightPanel=new CardPanel(this,CardPanel.RIGHT);
    	contentPane.add(rightPanel);
    	rightPanel.setBounds(590,50,100,280);
    	rightPanel.setType(2);
    	rightPanel.setVisible(true);
    	
    	rightPlayPane=new CardPanel(this,CardPanel.RIGHT_PLAY);
    	contentPane.add(rightPlayPane);
    	rightPlayPane.setBounds(350,150,220,100);
    	rightPlayPane.setType(1);
    	rightPlayPane.setVisible(true);    	
    	
    	leftPanel=new CardPanel(this,CardPanel.LEFT);
    	contentPane.add(leftPanel);
    	leftPanel.setBounds(110,50,100,280);
    	leftPanel.setType(2);
    	leftPanel.setVisible(true);

    	leftPlayPane=new CardPanel(this,CardPanel.LEFT_PLAY);
    	contentPane.add(leftPlayPane);
    	leftPlayPane.setBounds(210,150,300,100);
    	leftPlayPane.setType(1);
    	leftPlayPane.setVisible(true);    	    	
    	
    	buttonPanel=new ButtonPanel(this);
    	contentPane.add(buttonPanel);
    	buttonPanel.setBounds(280,370,320,30);
    	buttonPanel.setVisible(true);
    	
    	playerPanel=new PlayerPanel(this);
    	contentPane.add(playerPanel);
    	playerPanel.setBounds(100,370,100,150);
    	playerPanel.setLink(0);
    	playerPanel.setPic("player.gif");
    	playerPanel.setVisible(false);
    	
    	rightPlayerPanel=new PlayerPanel(this);
    	contentPane.add(rightPlayerPanel);
    	rightPlayerPanel.setBounds(680,140,100,150);
    	rightPlayerPanel.setLink(1);
    	rightPlayerPanel.setPic("rightPlayer.gif");    	
    	rightPlayerPanel.setVisible(false);
    	
    	leftPlayerPanel=new PlayerPanel(this);
    	contentPane.add(leftPlayerPanel);
    	leftPlayerPanel.setBounds(10,140,100,150);
    	leftPlayerPanel.setLink(2);
    	leftPlayerPanel.setPic("leftPlayer.gif");
    	leftPlayerPanel.setVisible(false);
    	
    	scorePanel=new ScorePanel(this);
    	contentPane.add(scorePanel);
    	scorePanel.setBounds(590,420,200,110);
    	scorePanel.setVisible(true);
	}

	public void run(){
		try{
			socket=new Socket(InetAddress.getByName(host),port);
			}catch(IOException ex){ ex.printStackTrace();}
		conn=new Connection(socket);	
		player=new Player();
		if(name==null){
			player.name=System.getProperty("user.name");
		}
		else player.name=name;
		player.setConn(conn);
		table=new Table();
		playerPanel.setVisible(true);
		rightPlayerPanel.setVisible(true);
		leftPlayerPanel.setVisible(true);
		while (true){			
			perform(conn.receiveMsg());
			}
		}	
		
	public static void main(String [] args){
		CardClient cc=new CardClient();
		}
		
	private void auction(String str){
		int seat=Connection.getIntValue("seat",str);
		table.bid=Connection.getIntValue("bid",str);
		table.setGameState(Table.AUCTION);
		if(player.seatNum==seat&&player.state== Player.READY){
			player.state= Player.THINKING;
			buttonPanel.checkState();
		}
	}	
		
	public 	void perform(String str){
		int cmd=Connection.CMD_ILLEGAL;
		String type;
		String playerID;
		int [] cardsValue;
		//this.lstMsg.add("receiveMsg"+str); //debug
		
		cmd=conn.getCmd(str);
		switch(cmd){
		case Connection.CMD_SETID: setID(str);break;
		case Connection.CMD_JOIN: playerJoin(str);break;
		case Connection.CMD_READY: playerReady(str);break;
		case Connection.CMD_TABLEINFO: tableInfo(str);break;
		case Connection.CMD_DEALCARDS: dealCards(str);break;
		case Connection.CMD_AUCTION: auction(str);break;
		case Connection.CMD_SETLANDLORD: setLandlord(str);break;
		case Connection.CMD_PLAY: play(str);break;
		case Connection.CMD_WIN: win(str);break;
		}
	}
		
	private void dealCards(String str){
		int [] cardsValue;
		cardsValue=conn.getCards(str);
		java.util.Arrays.sort(cardsValue);
		player.receiveCards(cardsValue);
		cardPanel.refresh();
		int cards[]=new int[17];
		Arrays.fill(cards,55);
		table.players[(player.seatNum+1)%3].receiveCards(cards);
		rightPanel.refresh();
		cards=new int[17];
		Arrays.fill(cards,55);
		table.players[(player.seatNum+2)%3].receiveCards(cards);
		leftPanel.refresh();
		table.lastCards=new int[3];
		Arrays.fill(table.lastCards,55);
		topPanel.refresh();
	}	
		
	
	private void setLandlord(String str){
		int id=Connection.getIntValue("ID",str);
		table.landlord=id;//Connection.getIntValue("seat",str);
		table.currentPlayer=Connection.getIntValue("seat",str);//id;
		table.bid=Connection.getIntValue("bid",str);
		table.scoreMultiple=1;

		int[] cards=Connection.getCards(str);
		table.setLastCards(cards);
		topPanel.refresh();
		table.setGameState(Table.NEWLOOP);
		if(player.id==id) {
			player.receiveCards(cards);
			cardPanel.refresh();
			player.setState(Player.THINKING);
			buttonPanel.checkState();
		}
		else{
			int []newCards=new int[3];
			java.util.Arrays.fill(newCards,55);
			int seatNum=Connection.getIntValue("seat",str);
			table.players[seatNum].receiveCards(newCards);
			if(seatNum==(player.seatNum+1)%3) rightPanel.refresh();/*rightPanel.setCards(table.players[seatNum].getCards());*/
			else if(seatNum==(player.seatNum+2)%3) leftPanel.refresh();//leftPanel.setCards(table.players[seatNum].getCards());
		}
		table.setGameState(Table.NEWLOOP);
		repaint();
	}
		
	public void play(String str){
		int [] cards=Connection.getCards(str);
		CardType cardType=Rule.getType(cards);
		if(cardType.type==Rule.BOMB||cardType.type==Rule.ROCKET) table.scoreMultiple*=2;
		int seatNum=Connection.getIntValue("seat",str);
		if(cards[0]==0) {//player pass
			Debug.println("Player pass"+seatNum);
			table.players[seatNum].setDisCards(cards);
			table.passTime++;
			rightPlayPane.refresh();
			leftPlayPane.refresh();
			bottomPlayPane.refresh();
			}
		else if(player.seatNum==seatNum){
			player.removeCards(cards);
			player.setDisCards(cards);
			int [] newCards=new int[cards.length];
			System.arraycopy(cards,0,newCards,0,cards.length);
			table.bigCards=newCards;
			cardPanel.refresh();
			bottomPlayPane.refresh();
			table.passTime=0;
		}
		else{
			int [] newCards=new int[cards.length];
			java.util.Arrays.fill(newCards,55);
			table.players[seatNum].removeCards(newCards);
			table.players[seatNum].setDisCards(cards);
			newCards=new int[cards.length];
			System.arraycopy(cards,0,newCards,0,cards.length);
			table.bigCards=newCards;
			if(seatNum==(player.seatNum+1)%3) {rightPanel.refresh();rightPlayPane.refresh();}
			else if(seatNum==(player.seatNum+2)%3) {leftPanel.refresh();leftPlayPane.refresh();}
			table.passTime=0;
			}
				
		table.players[table.currentPlayer].setState(Player.WAIT_OTHER);
		table.currentPlayer=(table.currentPlayer+1)%3;
		if(table.gameState==Table.NEWLOOP) table.setGameState(Table.PLAY);
		if(table.passTime==2){
			table.curLoop++;
			table.passTime=0;
			for(int i=0;i<3;i++) table.players[i].clearDisCards();
			bottomPlayPane.refresh();
			rightPlayPane.refresh();
			leftPlayPane.refresh();
			table.setGameState(Table.NEWLOOP);
		}
		table.players[table.currentPlayer].setState(Player.THINKING);
		for(int i=0;i<3;i++){
			if(table.players[i].cardNum()==0) {
				win(i);
				return;
			}
		}
		buttonPanel.checkState();
		if(player.autoPlay) autoPlay();
	}	
	
	void	btnStart_actionPerformed(ActionEvent e){
		String msg="cmd="+Connection.CMD_READY
					+"&seat="+player.seatNum
					+"&ID="+player.id;
		player.conn.sendMsg(msg);
		}	
			
	public void startServer(int port){
    	GameServer server=new GameServer(port);
    	Thread t=new Thread(server);
    	t.start();
	}

    public void addRobot(){
		Robot robot = new Robot(1);
		robot.start();
	}
    	
    public void joinGame(String host,int port){
    	Thread t=new Thread(this);
    	t.start();
    	}
    private void joinTable(){
    	String msg;
    	msg="cmd="+Connection.CMD_JOIN+"&ID="+player.id;
    	player.conn.sendMsg(msg);
    }
    private void sendPlayerInfo(){
    	String msg;
    	msg="cmd="+Connection.CMD_USERINFO
    		+"&ID="+player.id
    		+"&name="+player.name
    		+"&score="+player.score;
    	player.conn.sendMsg(msg);
    	}	
    private void setID(String str){
    	player.setID(Connection.getValue("ID",str));
    	sendPlayerInfo();
    	joinTable();
    }
    	
	private void playerJoin(String str){
		int id=Integer.parseInt(Connection.getValue("id",str));
		String name=Connection.getValue("name",str);
		int score=Integer.parseInt(Connection.getValue("score",str));
		int seat=Integer.parseInt(Connection.getValue("seat",str));
		if(id==player.id){
			player.seatNum=seat;
			table.addPlayer(player,seat);
			waitReady();
			} 
		else {
			Player m=new Player();
			m.id=id;
			m.name=name;
			m.score=score;
			m.seatNum=seat;
			table.addPlayer(m,seat);
		}
		repaint();		
	}
	
	private void waitReady(){
		btnStart.setVisible(true);
		}
	
	private void playerReady(String str){
		int seat,id;
		seat=Connection.getIntValue("seat",str);
		id=Connection.getIntValue("id",str);
		table.players[seat].setState(Player.READY);
		if(id==player.id) btnStart.setVisible(false);
	}
	
	private void tableInfo(String str){
		int playerNum=Connection.getIntValue("playerNum",str);
		int seat,id,seatNum,score,state;
		String name;
		for(int i=0;i<3;i++){
			seat=Connection.getIntValue("seat"+i,str);
			if(seat==1){
				id=Connection.getIntValue("id"+i,str);
				seatNum=Connection.getIntValue("seatNum"+i,str);
				score=Connection.getIntValue("score"+i,str);
				state=Connection.getIntValue("getGameState"+i,str);
				name=Connection.getValue("name"+i,str);
				Player m=new Player(id);
				m.setName(name);
				m.setScore(score);
				m.setState(state);
				table.addPlayer(m,seatNum);
			}
		}
	}
	
	private void win(String str){
		int seat=Connection.getIntValue("seat",str);
		if(seat==player.seatNum) player.score+=2*(table.bid)*table.scoreMultiple;
		else player.score=player.score-table.bid*table.scoreMultiple;
		WinDialog wf=new WinDialog(this,table.players[seat].name);
		wf.setLocationRelativeTo(this);
		wf.setVisible(true);
	}
	
	private void win(int seat){
		for(int i=0;i<3;i++){
			table.players[i].preScore=(table.bid)*table.scoreMultiple;
			int j;
			if(table.players[seat].id==table.landlord){//地主赢了
				if(table.players[i].id==table.landlord) j=2;//i是地主
				else j=-1;//如果不是地主
			}
			else{//地主输了
				if(table.players[i].id==table.landlord) j=-2;
				else j=1;
			}
			table.players[i].preScore*=j;
			table.players[i].score+=table.players[i].preScore;
		}
		
		String msg="cmd="+Connection.CMD_WIN
					+"&ID="+table.players[seat].id
					+"&seat="+table.players[seat].seatNum;
		player.conn.sendMsg(msg);
		
		WinDialog wf=new WinDialog(this,table.players[seat].name);
		wf.setLocationRelativeTo(this);
		wf.setVisible(true);
	}
	
	public void newGame(){
		table.newGame();
		cardPanel.refresh();
		buttonPanel.checkState();
		bottomPlayPane.refresh();
		topPanel.refresh();
		rightPlayPane.refresh();
		leftPlayPane.refresh();
		rightPanel.refresh();
		leftPanel.refresh();
		waitReady();
		repaint();
	}
	
	public void autoSelect(){
		int [] newCards;
		if(table.gameState==Table.NEWLOOP&&table.currentPlayer==player.seatNum)
		{
			newCards=Rule.getSmallCards(player.getCards());
			cardPanel.selectCards(newCards);
		}
		else{
			newCards=Rule.canPlay(player.getCards(),table.getBigCards());
		//if(cardType.type!=Rule.ILLEGAL) {
		//	int [] newCards=Rule.getCards(player.getCards(),cardType);
			if(newCards==null) buttonPanel.pass();
			cardPanel.selectCards(newCards);
		}
		//}
	}
	
	public void autoPlay(){
		int [] newCards;
		//Debug.println("In CardClient.autoPlay()");
		if((table.gameState==Table.PLAY||table.gameState==Table.NEWLOOP)&&player.state== Player.THINKING){
		if(table.gameState==Table.NEWLOOP&&table.currentPlayer==player.seatNum)
		{
			newCards=Rule.getSmallCards(player.getCards());
			//cardPanel.selectCards(newCards);
			buttonPanel.playCards(newCards);
		}
		else{
			newCards=Rule.canPlay(player.getCards(),table.getBigCards());
			if(newCards==null) {buttonPanel.pass();return;}
			buttonPanel.playCards(newCards);
		}
		}
	}

	public int getPort() {
		return port;
	}

	public void setPort(int port) {
		this.port = port;
	}

	public String getHost() {
		return host;
	}

	public void setHost(String host) {
		this.host = host;
	}

	@Override
	public String getName() {
		return name;
	}

	@Override
	public void setName(String name) {
		this.name = name;
	}

	public Socket getSocket() {
		return socket;
	}

	public void setSocket(Socket socket) {
		this.socket = socket;
	}

	public Connection getConn() {
		return conn;
	}

	public void setConn(Connection conn) {
		this.conn = conn;
	}
}